import os
import sys
import gdal
import zipfile
import paramiko
from tqdm import tqdm
from gdal import osr
from gdal import ogr
import re
import pathlib
import cv2
import numpy as np


class UniversalFileProcess:

    def __init__(self):
        pass

    @staticmethod
    def GetSubFile(pardir):
        """
        获取该文件夹下所有子文件路径
        """
        names = os.listdir(pardir)
        subfiles = []
        for name in names:
            unkownpath = os.path.join(pardir, name)
            if os.path.isfile(unkownpath):
                subfiles.append(unkownpath)
        return subfiles

    @staticmethod
    def GetSubDir(pardir):
        """获得所有子目录完整路径"""
        names = os.listdir(pardir)
        subdirs = []
        for name in names:
            unkownpath = os.path.join(pardir, name)
            if os.path.isdir(unkownpath):
                subdirs.append(unkownpath)
        return subdirs

    @staticmethod
    def HanziToPinyin(instr):
        """判断字符串中是否包含中文字符，若有，则用中文拼替换，没有，则返回原字符串"""
        outstrs = list(instr)
        strc = len(outstrs)
        for index in range(strc):
            if '\u4e00' <= outstrs[index] <= '\u9fff':
                hanzistr = outstrs[index]
                pinyinstrs = lazy_pinyin(hanzistr)  # 返回的是拼音列表
                pinyinstr = pinyinstrs[0]
                capitalpp = pinyinstr[0].upper() + pinyinstr[1:]
                outstrs[index] = capitalpp
        outstr = "".join(outstrs)
        return outstr

    @classmethod
    def LayerNamrCnToEn(cls, dsname, lyname):
        """保证图层名一定不含中文字符"""
        ds = ogr.Open(dsname)
        if not lyname:
            ly = ds.GetLayer(0)
        else:
            ly = ds.GetLayerByName(lyname)
        lyname = ly.GetName()
        pylyname = cls.HanziToPinyin(lyname)
        if pylyname != lyname:
            drivername = 'ESRI Shapefile'
            gdal.SetConfigOption("GDAL_FILENAME_IS_UTF8", "YES")
            gdal.SetConfigOption("SHAPE_ENCODING", "GBK")
            driver = ogr.GetDriverByName(drivername)
            shpdir, dssign = os.path.split(dsname)
            rdsname = os.path.join(shpdir, dssign + "_PY")
            if os.path.exists(rdsname):
                shutil.rmtree(rdsname)
            rds = driver.CreateDataSource(rdsname)
            rds.CopyLayer(ly, pylyname)
            rds.Destroy()
            ds.Destroy()
            return [rdsname, pylyname]
        ds.Destroy()
        return [dsname, lyname]
    
    @staticmethod
    def UnzipFile(zippath, unzipdir):
        """解压文件"""
        zipfilesign = os.path.splitext(os.path.split(zippath)[1])[0]
        unzipfilepath = os.path.join(unzipdir, zipfilesign)
        if os.path.exists(unzipfilepath):
            return print(unzipfilepath, ":解压文件存在！")
        else:
            os.makedirs(unzipfilepath)
        rasterzipfile = zipfile.ZipFile(zippath, "r")
        for file in rasterzipfile.namelist():
            rasterzipfile.extract(file, unzipfilepath)
        rasterzipfile.close()
        return unzipfilepath

    @staticmethod
    def ZipFile(folderorfile, savedir=None):
        """
        压缩文件
        :param folderorfile: 需要压缩的文件夹路径
        :param savedir: 保存压缩文件的目录
        :return:
        """
        if os.path.isfile(folderorfile):
            unzipfilepath = folderorfile
            [basepath, unzipfilename] = os.path.split(unzipfilepath)
            filename = os.path.splitext(unzipfilename)[0]
            zipfilename = filename + r".zip"
            if savedir is None:
                zipfilepath = os.path.join(basepath, zipfilename)
            else:
                zipfilepath = os.path.join(savedir, zipfilename)
            zipfileobject = zipfile.ZipFile(
                zipfilepath, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=6)
            zipfilesubfoldername = os.sep + unzipfilename
            zipfileobject.write(unzipfilepath, zipfilesubfoldername)
            zipfileobject.close()
            return zipfilepath
        elif os.path.isdir(folderorfile):
            folderpath = folderorfile
            [basepath, foldername] = os.path.split(folderpath)
            zipfilename = foldername + r".zip"
            if savedir is None:
                zipfilepath = os.path.join(basepath, zipfilename)
            else:
                zipfilepath = os.path.join(savedir, zipfilename)
            zipfileobject = zipfile.ZipFile(
                zipfilepath, "w", compression=zipfile.ZIP_DEFLATED, compresslevel=6)
            for parentdir, subfoldernamelist, filenamelist in os.walk(folderpath):
                subfoldername = parentdir.replace(folderpath, '')
                subfoldername = subfoldername and subfoldername + os.sep or ''
                for filename in filenamelist:
                    foldersubfilepath = os.path.join(parentdir, filename)
                    zipfilesubfoldername = os.path.join(subfoldername, filename)
                    zipfileobject.write(foldersubfilepath, zipfilesubfoldername)
            zipfileobject.close()
            return zipfilepath
        else:
            print("文件压缩失败!")
        return

    @classmethod
    def GetGoalFile(cls, infolder, sign=None):
        """搜索获得目标文件路径集"""
        if sign is None:
            return cls.FindAllFile(infolder)
        elif sign[0] == r".":
            filepaths = cls.FindAllFile(infolder)
            rasfilepaths = [
                filepath
                for filepath in filepaths
                if os.path.splitext(os.path.split(filepath)[1])[1] == sign]
            return rasfilepaths
        else:
            filepaths = self.FindAllFile(infolder)
            rasfilepaths = [
                filepath
                for filepath in filepaths
                if os.path.splitext(os.path.split(filepath)[1])[0] == sign]
            return rasfilepaths

    @classmethod
    def FindAllFile(cls, infolder):
        """寻找该目录下的所有文件"""
        names = os.listdir(infolder)
        filepaths = []
        for name in names:
            unkownfilefolder = os.path.join(infolder, name)
            if os.path.isfile(unkownfilefolder):
                filepaths.append(unkownfilefolder)
            elif os.path.isdir(unkownfilefolder):
                filepaths = filepaths + cls.FindAllFile(unkownfilefolder)
        return filepaths

    @staticmethod
    def ClipImage(imgfilepath, winsize, stride, savedir):
        """
        裁剪图片，尽量不使用中文路径, 临时
        :param imgfilepath:
        :param winsize:
        :param stride:
        :param savedir:
        :return:
        """
        imgfilename = os.path.split(imgfilepath)[1]
        filename = os.path.splitext(imgfilename)[0]
        clipimgfilefolder = os.path.join(savedir, filename)
        if not os.path.exists(clipimgfilefolder):
            os.makedirs(clipimgfilefolder)
        image = cv2.imdecode(np.fromfile(imgfilepath, dtype=np.uint8), -1)
        height, width, channls = image.shape
        [winwidth, winheight] = winsize
        [stridex, stridey] = stride
        winycount = int(height/winheight)
        winxcount = int(width/winwidth)
        wincountindexlist = []
        for winxindex in range(winxcount):
            for winyindex in range(winycount):
                winimage = image[
                      int(winyindex * winheight):int(winyindex * winheight) + winheight,
                      int(winxindex * winwidth):int(winxindex * winwidth) + winwidth]
                winimagename = filename+"_"+str(winxindex)+"_"+str(winyindex)+".jpg"
                winimagepath = os.path.join(clipimgfilefolder, winimagename)
                print(winimagepath)
                cv2.imwrite(winimagepath, winimage)
        return
    
    
UFP = UniversalFileProcess()